Terminology Services
A terminology service is the component that knows what codes mean. It holds the code systems, the value sets that constrain each coded field, and the maps between local and standard vocabularies — and it answers questions about them over an API instead of inside each application's source code.
It is the least glamorous shared service in a health architecture and the one whose absence causes the most silent data corruption.
Why it must be a service
Without one, terminology lives in three places, all of them bad:
- Hard-coded in application source — changing a code requires a release
- Duplicated in every system's database — six systems, six divergent copies of the drug list, none authoritative
- In a spreadsheet emailed by a terminologist — the honest state of most programmes
Each is a decay mechanism. Codes drift apart, mappings go stale, and the aggregate statistics computed on top of them quietly become wrong. Nobody notices, because nothing errors.
Centralising terminology gives you a single place to update, an audit trail of changes, and the ability to answer "when did this value set change, and what does that do to the trend?"
What it does
| Function | Example question |
|---|---|
| Lookup | What does LOINC 8867-4 mean? |
| Validation | Is this code valid in this value set for this field? |
| Expansion | List every code in "notifiable conditions" |
| Subsumption | Is "type 2 diabetes" a kind of "diabetes mellitus"? |
| Translation | What is the ICD-10 equivalent of this SNOMED CT concept? |
| Search | Find concepts matching "bp" for a clinician's type-ahead |
| Versioning | Which version of ICD-10 was in force when this was coded? |
Subsumption is the one that distinguishes a terminology server from a lookup table. "Give me every patient with a diabetes diagnosis" only works if the service can reason over the hierarchy — otherwise the query has to enumerate hundreds of codes, and will miss the ones added last year.
The FHIR terminology API
FHIR defines the operations, so a terminology service is interchangeable:
GET /CodeSystem/$lookup?system=http://loinc.org&code=8867-4
GET /ValueSet/$expand?url=http://example.org/ValueSet/notifiable-conditions
GET /ValueSet/$validate-code?url=…&system=…&code=…
GET /CodeSystem/$subsumes?system=…&codeA=…&codeB=…
GET /ConceptMap/$translate?url=…&system=…&code=…&targetsystem=…
Three resource types carry the content:
CodeSystem— defines the concepts (or declares that they are defined elsewhere, as with SNOMED CT and LOINC)ValueSet— a set of codes selected from one or more code systems, either enumerated or defined by an expression.ValueSetis what a field binds to.ConceptMap— relationships between codes in different systems, with an equivalence assertion (equivalent,wider,narrower,inexact)
The ConceptMap equivalence field is not decoration. A map marked
equivalent may be applied automatically; one marked wider loses information
and needs a documented decision about whether that is acceptable for the purpose
at hand. Maps that assert equivalence they do not have are how coded data
becomes wrong.
Value set governance
Value sets are the operational core, and they need process, not just a server.
Binding strength decides what happens to data that does not fit:
| Strength | Means | Use for |
|---|---|---|
required | Must be from this set | Small, stable, complete sets — administrative gender, yes/no |
extensible | Use one if it fits; otherwise supply your own | Most clinical concepts |
preferred | Encouraged | Emerging domains |
example | Illustrative only | Almost nothing in a national IG — this is where interoperability goes to die |
Intensional versus extensional. An extensional value set enumerates codes; an
intensional one defines them by a rule ("all descendants of SNOMED CT
73211009 | Diabetes mellitus |"). Intensional sets stay current automatically
and are the better default — but they mean the expansion changes when the code
system is updated, which is exactly why expansions must be versioned and
dated wherever they affect reporting.
Governance questions to answer before go-live:
- Who may create a value set, and who approves it?
- How is a change requested, reviewed and published?
- What is the release cadence, and how are consumers notified?
- How long are old versions retained? (Answer: as long as data coded against them is retained.)
- Who maintains the local-to-standard maps as source systems change?
- What happens to a value set when the underlying code system releases a new version — retire, remap, or freeze?
See governance.
Open-source and available options
| Option | Notes | Tier |
|---|---|---|
| Snowstorm | SNOMED International's open-source SNOMED CT terminology server, with FHIR API support | 2 |
| Ontoserver | CSIRO terminology server; widely used nationally, licensed (free for some jurisdictions) | 2 |
| HAPI FHIR terminology module | Terminology services within the HAPI FHIR server; adequate for many deployments | 2 |
| OpenCodeSystems / OCL (Open Concept Lab) | Terminology management and dictionary curation, used with OpenMRS | 2 |
| tx.fhir.org | HL7's public terminology server — for validation and development, not for production dependency | 1 |
| Cloud terminology services | Offered by the major providers alongside their FHIR services | 2 |
Choose on: which code systems it can host (SNOMED CT support is the usual discriminator), whether it supports intensional expansion and subsumption, whether it can be run in-country, and whether anyone will operate it.
Where it sits
Point-of-service systems Interoperability layer
(type-ahead, validation) (transformation, mapping)
│ │
└────────────┬───────────────────┘
▼
┌──────────────────────┐
│ Terminology service │
│ CodeSystem │
│ ValueSet │
│ ConceptMap │
└──────────┬───────────┘
│
▼
Analytics / reporting / surveillance
(cohort definitions by value set)
The same value set that constrains data entry should define the analytics cohort. When those are maintained separately — one in the EMR, one in the reporting SQL — they diverge, and the numbers stop matching the record.
Availability. If clinical systems call the terminology service synchronously during data entry, it is on the critical path for care. Either make it highly available, or cache expansions locally with a defined refresh — usually both.
Getting started without boiling the ocean
- Take an inventory of coded fields across existing systems, and what each is coded with today
- Pick the three that matter most — usually diagnosis, laboratory test, and medication
- Bind each to a national value set, published and versioned
- Publish
ConceptMaps from each system's local codes to those value sets - Move the interoperability layer's translation logic out of code and onto those maps
- Only then consider full SNOMED CT licensing and extension management
References
- FHIR terminology module — https://hl7.org/fhir/terminology-module.html
- FHIR
ValueSet— https://hl7.org/fhir/valueset.html - FHIR
ConceptMap— https://hl7.org/fhir/conceptmap.html - Snowstorm — https://github.com/IHTSDO/snowstorm
- Ontoserver — https://ontoserver.csiro.au/
- Open Concept Lab — https://openconceptlab.org/
- HL7 public terminology server — https://tx.fhir.org/